package me.magicall.web.simple.spring.controllers;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import me.magicall.coll.CollFactory;
import me.magicall.consts.CommonConst;
import me.magicall.convenient.ResultView;
import me.magicall.db.model.BaseModel.MapModel;
import me.magicall.db.outsea.ListSqlConfig;
import me.magicall.db.outsea.springjdbc.Count;
import me.magicall.db.outsea.springjdbc.GetList;
import me.magicall.db.util.PageInfo;
import me.magicall.db.util.PageInfo.PageMode;
import me.magicall.util.kit.Kits;
import me.magicall.web.simple.spring.util.C;
import me.magicall.web.simple.spring.util.U;
import me.magicall.web.simple.spring.util.UrlPatternRule;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @author MaGiCalL
 */
@Controller("listController")
@RequestMapping(method = RequestMethod.GET, //
value = { UrlPatternRule.SINGULAR_MODEL_NAME + "s",//仅以s结尾的复数形式
		UrlPatternRule.SINGULAR_MODEL_NAME + "/list"//
})
public class ListController {
//	@Autowired
//	private MapModelAccessor mapModelAccessor;
	@Autowired
	private GetList<MapModel<?>> getList;
	@Autowired
	private Count<MapModel<?>> count;

	private final int pageSize;

	public ListController(final int pageSize) {
		super();
		this.pageSize = pageSize;
	}

	@SuppressWarnings("unchecked")
	@RequestMapping
	public String listAll(final HttpServletRequest request, final ModelMap modelMap,//
			@PathVariable("modelName") final String modelName) {//
		final Map<String, Object> paramterMap = (Map<String, Object>) request.getAttribute(C.REQUEST_PARAMS_NAME);// request.getParameterMap();

		final ListSqlConfig<MapModel<?>> sqlConfig = getList.createSqlConfig(modelName);
		sqlConfig.addConditions(paramterMap);
		final ResultView<MapModel<?>> rv = U.resultView(sqlConfig, getList, count);
//				mapModelAccessor.listWithPageInfo(modelName, paramterMap, C.ALL_PAGE_INFO);

		final Collection<MapModel<?>> list = rv.getList();
		return dispatch(modelMap, modelName, list);
	}

	@SuppressWarnings("unchecked")
	@RequestMapping(UrlPatternRule.PAGE)
	public String listPaged(final HttpServletRequest request, final ModelMap modelMap,//
			@PathVariable("modelName") final String modelName,//
			@PathVariable("page") int page) {
		final PageMode defaultPageMode = getDefaultMode();
		if (page < defaultPageMode.firstPage) {
			page = defaultPageMode.firstPage;
		}
		final Map<String, Object> paramterMap = (Map<String, Object>) request.getAttribute(C.REQUEST_PARAMS_NAME);// request.getParameterMap();
		final PageInfo pageInfo = PageInfo.pageAndSize(page, pageSize);
		final ListSqlConfig<MapModel<?>> sqlConfig = getList.createSqlConfig(modelName);
		sqlConfig.addConditions(paramterMap);
		sqlConfig.setPageInfo(pageInfo);
		final ResultView<MapModel<?>> rv = U.resultView(sqlConfig, getList, count);
//				mapModelAccessor.listWithPageInfo(modelName, paramterMap, pageInfo);

		modelMap.addAttribute("maxPage", rv.getPageCount());
		modelMap.addAttribute("curPage", page);

		return dispatch(modelMap, modelName, rv.getList());
	}

	@RequestMapping({ UrlPatternRule.IDS, UrlPatternRule.IDS_RANGE })
	@Deprecated
	public String list(final ModelMap modelMap,//
			@PathVariable("modelName") final String modelName,//
			@PathVariable("ids") final String idStr) {
		String page;
		final List<? extends Comparable<?>> ids;
		if (Kits.STR.isEmpty(idStr)) {
			ids = CollFactory.L.seq(1, pageSize);
			page = "1";
		} else if (idStr.indexOf('~') > CommonConst.NOT_FOUND_INDEX) {
			ids = U.parseNumbers(idStr, pageSize);
			page = "1";
		} else {
			final Long i = Kits.LONG.fromString(idStr);
			if (i == null) {
				ids = CollFactory.L.seq(1, pageSize);
				page = "1";
			} else {
				final long start = (i - 1) * pageSize + 1;
				ids = CollFactory.L.seq(start, pageSize);
				page = idStr;
			}
		}
		final Collection<MapModel<?>> models = U.getById(modelName, ids, getList);//mapModelAccessor.list(modelName, ids);

		modelMap.addAttribute("curPage", page);
		return dispatch(modelMap, modelName, models);
	}

	private String dispatch(final ModelMap modelMap, final String modelName, final Collection<MapModel<?>> models) {
		U.setModelName(modelMap, modelName);
		if (models.size() == 1) {
			U.setOne(modelMap, models.iterator().next());
			return modelName;
		} else {
			modelMap.addAttribute(modelName + "s", models);
			modelMap.addAttribute("list", models);
			return modelName + "s";
		}
	}

	protected PageMode getDefaultMode() {
		return C.DEFAULT_PAGE_MODE;
	}
}
